package com.dreamwhale.machinery.H5pay;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayTradeWapPayModel;
import com.alipay.api.request.AlipayTradeWapPayRequest;
import com.alipay.api.response.AlipayTradeWapPayResponse;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.dreamwhale.machinery.adviceException.DragonException;
import com.dreamwhale.machinery.config.DataResult;
import com.dreamwhale.machinery.dao.*;
import com.dreamwhale.machinery.entity.*;
import com.dreamwhale.machinery.goods.entity.YxStoreCart;
import com.dreamwhale.machinery.goods.entity.YxStoreOrder;
import com.dreamwhale.machinery.goods.mapper.YxStoreCartMapper;
import com.dreamwhale.machinery.goods.mapper.YxStoreOrderMapper;
import com.dreamwhale.machinery.goods.service.YxStoreCartService;
import com.dreamwhale.machinery.goods.service.YxStoreOrderService;
import com.dreamwhale.machinery.pay.ali.server.AliPayService;
import com.dreamwhale.machinery.pay.weChat.config.WeChatConfig;
import com.dreamwhale.machinery.pay.weChat.utils.Md5Util;
import com.dreamwhale.machinery.pay.weChat.utils.PrepayIdRequestHandler;
import com.dreamwhale.machinery.pay.weChat.utils.WxNotifyParam;
import com.dreamwhale.machinery.service.UserApplyService;
import com.dreamwhale.machinery.service.YxStoreProductService;
import com.dreamwhale.machinery.user.entity.UserShop;
import com.dreamwhale.machinery.user.entity.YxUser;
import com.dreamwhale.machinery.user.entity.YxUserAddress;
import com.dreamwhale.machinery.user.mapper.UserShopMapper;
import com.dreamwhale.machinery.user.mapper.YxUserMapper;
import com.dreamwhale.machinery.user.service.YxUserAddressService;
import com.dreamwhale.machinery.utils.WorkIdUtils;
import com.dreamwhale.machinery.wxConfig.GetWxOrderno;
import com.dreamwhale.machinery.wxConfig.RequestHandler;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.params.HttpMethodParams;
import org.apache.commons.lang.StringUtils;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;

@RestController
@RequestMapping("/pay")
public class AlipaysController {


    @Resource
    private VipInfoMapper vipInfoMapper;
   @Resource
    private YxUserMapper yxUserMapper;
    @Resource
    private YxStoreOrderMapper yxStoreOrderMapper;
    @Resource
    private UserApplyMapper userApplyMapper;
    @Resource
    private DictDetailMapper dictDetailMapper;
    @Resource
    private VipUserInfoMapper vipUserInfoMapper;
    @Resource
    private UserApplyService userApplyService;
    @Resource
    private AliPayService aliPayService;
    @Resource
    private YxStoreCartService yxStoreCartService;
    @Resource
    private YxStoreProductService yxStoreProductService;
    @Resource
    private YxStoreProductAttrValueMapper yxStoreProductAttrValueMapper;
    @Resource
    private UserShopMapper userShopMapper;
    @Resource
    private YxUserAddressService yxUserAddressService;
    @Resource
    private YxStoreOrderService yxStoreOrderService;
    @Resource
    private YxStoreCartMapper yxStoreCartMapper;

     //字符编码格式 目前支持 gbk 或 utf-8
    public static String CHARSET = "utf-8";
    private static String appsecret_user = WeChatConfig.APP_ID;
    private static String partnerkey = WeChatConfig.APP_SECRET;

    /**
     * 学堂
     * @param request
     * @param response
     * @param orderId
     * @param userId
     * @param pid
     */
    @RequestMapping("orderApply")
    public void orderApply(HttpServletRequest request,HttpServletResponse response,String orderId, Integer userId, Integer pid) {

            UserApply userApply = userApplyMapper.selectById(orderId);
            HashMap<Object, Object> objectObjectHashMap = new HashMap<>();
            objectObjectHashMap.put("payType", 3);
            objectObjectHashMap.put("userId", userId);
            objectObjectHashMap.put("pid", pid);
        payWebPayPages(request,response,userApply.getApplyOrderId(), "测试", userApply.getApplyMoney().toString(),"测试" ,JSON.toJSONString(objectObjectHashMap));
    }

    /**
     * 机修学堂
     * @param name
     * @param phone
     * @param payType
     * @param
     * @param pid
     * @param request
     * @param response
     * @return
     */
    @RequestMapping("/userApply")
    public void userApply(String name, String phone, Integer payType, @RequestParam(defaultValue = "")Integer pid, HttpServletRequest request, HttpServletResponse response) {
        Integer userId = Integer.parseInt(request.getAttribute("userId").toString());;
                //Integer.parseInt(request.getAttribute("userId").toString());
        DictDetail dictDetail = dictDetailMapper.selectOne(new QueryWrapper<DictDetail>().eq("label", "apply"));
        UserApply userApply = new UserApply();
        String orderId = WorkIdUtils.generateOrderId();
        userApply.setApplyCreateTime(LocalDateTime.now());
        userApply.setApplyOrderId(orderId);
        userApply.setApplyName(name);
        userApply.setApplyPhone(phone);
        userApply.setApplyMoney(BigDecimal.valueOf(Double.parseDouble(dictDetail.getValue())));
        if (userApplyService.save(userApply)) {
            //  resultMap
            switch (payType) {
                case 1:
                     orderApply(request,response,orderId, userId, pid);
                    break;
                case 2:
                    HashMap<Object, Object> objectObjectHashMap = new HashMap<>();
                    objectObjectHashMap.put("payType", 0);
                    objectObjectHashMap.put("userId", userId);
                    orderPays(IdWorker.getIdStr(), null, userApply.getApplyMoney(), JSON.toJSONString(objectObjectHashMap), request, response);
                        System.out.println("===============================================================");
                        break;

                default:
                    throw new RuntimeException("未知支付方式");
            }

        }
        response.setContentType("text/plain; charset=UTF-8");
        try {
            PrintWriter out = response.getWriter();
            out.println(orderId);
        } catch (IOException e) {
            e.printStackTrace();
        }
//        return DataResult.ok();
    }

    /**
     * vip充值
     *
     * @param
     * @return
     */
    @RequestMapping("/buyVips")
    @Transactional
    public void buyVips(HttpServletRequest request,HttpServletResponse response,Integer vipId, Integer payType, Integer userId) {
        VipInfo vipInfo = vipInfoMapper.selectById(vipId);
        if (vipInfo == null) throw new DragonException("会员不存在");
        BigDecimal vipPrice = vipInfo.getVipPrice();
        BigDecimal discount = BigDecimal.ZERO;
        BigDecimal payment = vipPrice.subtract(discount);


        VipUserInfo vipUserInfo1 = vipUserInfoMapper.inquiryVipExpirationTime(userId);
        LocalDateTime expirationTime = vipUserInfo1 == null ? LocalDateTime.now() : vipUserInfo1.getExpirationTime();
        VipUserInfo vipUserInfo = new VipUserInfo();
        vipUserInfo.setVid(vipId);
        vipUserInfo.setUid(userId);
        vipUserInfo.setCreateTime(LocalDateTime.now());
        vipUserInfo.setPayOrderId(IdWorker.getIdStr());
        vipUserInfo.setPayMoney(payment);
        vipUserInfo.setExpirationTime(expirationTime.compareTo(LocalDateTime.now()) > 0
                ? expirationTime.plusMonths(vipInfo.getVipMonth())
                : LocalDateTime.now().plusMonths(vipInfo.getVipMonth())
        );
        if (vipUserInfoMapper.insert(vipUserInfo) == 1) {
            switch (payType) {
                case 0:
                    throw new DragonException("当前支付未开通");
                case 1:
                    VipUserInfo vipUserInfos = vipUserInfoMapper.selectById(vipUserInfo1.getPayOrderId());
                    HashMap<Object, Object> objectObjectHashMap = new HashMap<>();
                    objectObjectHashMap.put("payType", 3);
                    objectObjectHashMap.put("userId", userId);
                    payWebPayPages(request,response,vipUserInfos.getPayOrderId(),"",vipUserInfos.getPayMoney().toString(),"vip充值",objectObjectHashMap.toString());
                    break;
                case 2:
//                    return weChatPayServer.vipRecharge(vipUserInfo.getPayOrderId(), userId);
                default:
                    throw new DragonException("未知支付方式");
            }
            response.setContentType("text/plain; charset=UTF-8");
            try {
                PrintWriter out = response.getWriter();
                out.println(vipUserInfo1.getPayOrderId());
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }


    /**
     * 订单支付  生成订单
     * @param request
     * @param response
     * @param yxStoreCart
     * @param payType
     * @param addrId
     * @return
     * @throws AlipayApiException
     */
    @RequestMapping("/payOrders")
    @Transactional
    public DataResult generateOrder(HttpServletRequest request,HttpServletResponse response,YxStoreCart yxStoreCart, Integer payType, Integer addrId) throws AlipayApiException {

        //首先加入购物车
        yxStoreCart.setAddTime(LocalDateTime.now());
        if (yxStoreCartService.save(yxStoreCart)) {
//            List<Integer> longs = Collections.singletonList(yxStoreCart.getId().intValue());
            return generateTrolleyOrder(request,response,yxStoreCart.getId().toString(), payType, addrId);
        }
        return new DataResult(300, "订单创建失败", null);
    }

    /**
     * 生成购物车订单
     * @param request
     * @param response
     * @param trolleyIds
     * @param payType
     * @param addrId
     * @return
     * @throws AlipayApiException
     */
    @RequestMapping("/payTrolleyOrder")
    @Transactional
    public DataResult generateTrolleyOrder(HttpServletRequest request,HttpServletResponse response,String trolleyIds, Integer payType, Integer addrId) throws AlipayApiException {
        YxStoreOrder yxStoreOrder = new YxStoreOrder();
        yxStoreOrder.setAddTime(LocalDateTime.now());
        yxStoreOrder.setTotalPrice(BigDecimal.ZERO);
        yxStoreOrder.setTotalNum(0);
        yxStoreOrder.setFreightPrice(BigDecimal.ZERO);
        String[] a = trolleyIds.split(",");
        for (String string : a) {
            YxStoreCart yxStoreCart = yxStoreCartService.getById(string);
            YxStoreProduct storeProduct = yxStoreProductService.getById(yxStoreCart.getProductId());
            YxStoreProductAttrValue yxStoreProductAttrValue = yxStoreProductAttrValueMapper.
                    selectOne(new QueryWrapper<YxStoreProductAttrValue>().eq("product_id", yxStoreCart.getProductId())
                            .eq("suk", yxStoreCart.getProductAttrUnique()));
            if (storeProduct.getPostage() == null) {
                storeProduct.setPostage(BigDecimal.ZERO);
            }
            BigDecimal multiply = yxStoreProductAttrValue.getPrice().multiply(BigDecimal.valueOf(yxStoreCart.getCartNum()));
            BigDecimal total = multiply.add(storeProduct.getPostage());
            yxStoreOrder.setTotalPrice(yxStoreOrder.getTotalPrice().add(total));
            yxStoreOrder.setTotalNum(yxStoreOrder.getTotalNum() + yxStoreCart.getCartNum());

            yxStoreOrder.setFreightPrice(yxStoreOrder.getFreightPrice().add(storeProduct.getPostage()));
            yxStoreOrder.setUid(yxStoreCart.getUid());
            //商戶
            QueryWrapper<UserShop> userShopQueryWrapper = new QueryWrapper<>();
            userShopQueryWrapper.eq("id", storeProduct.getMerId());
            UserShop userShop = userShopMapper.selectOne(userShopQueryWrapper);
            yxStoreOrder.setMerId(userShop.getId().intValue());
        }
        yxStoreOrder.setCartId(trolleyIds);
        String orderId = WorkIdUtils.generateOrderId();
        yxStoreOrder.setOrderId(orderId);
        YxUserAddress userAddressInfo = yxUserAddressService.getById(addrId);
        yxStoreOrder.setRealName(userAddressInfo.getRealName());
        yxStoreOrder.setUserPhone(userAddressInfo.getPhone());
        yxStoreOrder.setUserAddress(JSON.toJSONString(userAddressInfo));
        if (yxStoreOrderService.save(yxStoreOrder)) {
            HashMap<String, Object> resultMap = new HashMap<>();
            resultMap.put("orderInfo", yxStoreOrderService.getById(yxStoreOrder.getId()));
            String cartId = yxStoreOrder.getCartId();
            switch (payType) {
                case 0://余额
                    break;
                case 1://支付宝
                    HashMap<Object, Object> objectObjectHashMap = new HashMap<>();
                    objectObjectHashMap.put("payType", 1);
                    objectObjectHashMap.put("userId", yxStoreOrder.getUid());
                    payWebPayPages(request,response,orderId, "测试", yxStoreOrder.getPayPrice().toString(),"测试" ,JSON.toJSONString(objectObjectHashMap));
                    break;
                case 2:

                     break;
            }
            resultMap.put("goodsInfo", yxStoreCartMapper.selectList(new QueryWrapper<YxStoreCart>().in("id", cartId)));
            return new DataResult(200, "订单创建成功", resultMap);
        }
        return new DataResult(300, "订单创建失败", null);
    }


    /**
     *订单支付
     * @param request
     * @param response
     * @param orderId
     * @param userId
     * @param payType
     */
//    @RequestMapping("/payOrders")
//    @Transactional
//    public void payOrders(HttpServletRequest request,HttpServletResponse response,String orderId, Integer payType) {
//
//        QueryWrapper<YxStoreOrder> yxStoreOrderQueryWrapper = new QueryWrapper<>();
//        yxStoreOrderQueryWrapper.eq("order_id", orderId);
//        YxStoreOrder yxStoreOrder = yxStoreOrderMapper.selectOne(yxStoreOrderQueryWrapper);
//            switch (payType) {
//                case 0://余额
//                    break;
//                case 1://支付宝
//                    HashMap<Object, Object> objectObjectHashMap = new HashMap<>();
//                    objectObjectHashMap.put("payType", 1);
//                    objectObjectHashMap.put("userId", yxStoreOrder.getUid());
//                    payWebPayPages(request,response,orderId, "测试", yxStoreOrder.getPayPrice().toString(),"测试" ,JSON.toJSONString(objectObjectHashMap));
//              break;
//                case 2:
////                    return weChatPayServer.order(yxStoreOrder.getId().toString(), yxStoreOrder.getUid(), null, null);
//            }
//
//
//    }



    /**
     * 吊起
     * @param request
     * @param response
     * @param out_trade_no
     * @param subject
     * @param total_amount
     * @param body
     * @param backJsonInfo
     */
    public void payWebPayPages(HttpServletRequest request, HttpServletResponse response,String out_trade_no ,String subject,String total_amount,String body,String backJsonInfo) {
        //调用RSA签名方式
        AlipayClient client = new DefaultAlipayClient(AlipayConfig.URL, AlipayConfig.APPID, AlipayConfig.RSA_PRIVATE_KEY, AlipayConfig.FORMAT, AlipayConfig.CHARSET, AlipayConfig.ALIPAY_PUBLIC_KEY,"RSA2");
        AlipayTradeWapPayRequest alipay_request = new AlipayTradeWapPayRequest();

        // 封装请求支付信息
        AlipayTradeWapPayModel model = new AlipayTradeWapPayModel();
        model.setOutTradeNo(out_trade_no);
        model.setSubject(subject);
        model.setTotalAmount(total_amount);
        model.setBody(body);
//        model.setTimeoutExpress("30m");
        model.setProductCode("QUICK_WAP_WAY");
        model.setPassbackParams(backJsonInfo);
        alipay_request.setBizModel(model);

        // 设置异步通知地址
        alipay_request.setNotifyUrl(AlipayConfig.notify_url);
        // 设置同步地址
        alipay_request.setReturnUrl(AlipayConfig.return_url);
        // form表单生产
        String form = "";
        try {
            // 调用SDK生成表单

            AlipayTradeWapPayResponse responseA = client.pageExecute(alipay_request);
            if(responseA.isSuccess()){
                System.out.println("调用成功");
            } else {
                System.out.println("调用失败");
            }
            form = responseA.getBody();
            System.out.println(form);
            response.setContentType("text/html;charset=" + AlipayConfig.CHARSET);
            response.getWriter().write(form);//直接将完整的表单html输出到页面
            response.getWriter().flush();
            response.getWriter().close();
        } catch (AlipayApiException | IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    /**
     *支付宝回调
     * @param request
     * @param response
     * @return
     */
    @RequestMapping("notify")
    public String notify(HttpServletRequest request, HttpServletResponse response) {
            String tradeStatus = request.getParameter("trade_status");
            String outTradeNo = request.getParameter("out_trade_no");
            String trade_no = request.getParameter("trade_no");
            String passbackParams = request.getParameter("passback_params");
            String totalAmount = request.getParameter("total_amount");
            JSONObject jsonObject = JSON.parseObject(passbackParams);
            String userId = jsonObject.get("userId").toString();
            String payType = jsonObject.get("payType").toString();
            Integer uid = Integer.parseInt(userId);
            BigDecimal bigDecimal = BigDecimal.valueOf(Double.parseDouble(totalAmount));

            //TODO:处理回调信息
            switch (Integer.parseInt(payType)) {
                case 0://充值

                    System.out.println("充值信息");
                    break;
                case 1://
                    YxStoreOrder yxStoreOrder = yxStoreOrderMapper.selectOne(new QueryWrapper<YxStoreOrder>().eq("order_id", outTradeNo));
                    yxStoreOrder.setPaid(true);
                    yxStoreOrder.setPayTime(LocalDateTime.now());
                    yxStoreOrderMapper.updateById(yxStoreOrder);
                    System.out.println("订单信息");
                    break;
                case 2://报名
                    UserApply applyOrder = userApplyMapper.selectById(new QueryWrapper<UserApply>().eq("apply_order_id", outTradeNo));
                    applyOrder.setApplyPayTime(LocalDateTime.now());
                    userApplyMapper.updateById(applyOrder);
                    Object pid1 = jsonObject.get("pid");
                    //给邀请的人一个奖励
                    if (pid1 != null) {
                        DictDetail dictDetail = dictDetailMapper.selectOne(new QueryWrapper<DictDetail>().eq("label", "applyAwards"));
                        BigDecimal decimal = BigDecimal.valueOf(Integer.parseInt(dictDetail.getValue()));
                        Integer pid = Integer.parseInt(pid1.toString());
                        VipUserInfo userInfo = vipUserInfoMapper.selectById(pid);
              
                        vipUserInfoMapper.updateById(userInfo);
                    }
                    break;
                case 3:

                    VipUserInfo vipUserInfo = vipUserInfoMapper.selectById(outTradeNo);
                    vipUserInfo.setPayTime(LocalDateTime.now());
                    vipUserInfoMapper.updateById(vipUserInfo);
                    if(userId!=null){

                    }
                    break;

                default:
                    break;
            }

            return "success";

    }



    // 通过xml 发给微信消息
    public static String setXml(String return_code, String return_msg) {
        SortedMap<String, String> parameters = new TreeMap<String, String>();
        parameters.put("return_code", return_code);
        parameters.put("return_msg", return_msg);
        System.out.println(parameters);
        return "<xml><return_code><![CDATA[" + return_code + "]]>" + "</return_code><return_msg><![CDATA[" + return_msg
                + "]]></return_msg></xml>";
    }


    public WxNotifyParam orderPays(String orderId, String body, BigDecimal money, String backJsonInfo, HttpServletRequest request, HttpServletResponse response) {
        PrepayIdRequestHandler prepayReqHandler = new PrepayIdRequestHandler(request, response);
        int value = money.multiply(BigDecimal.valueOf(100)).intValue();
        prepayReqHandler.setParameter("appid", "wxbc645cafc9875782");
        prepayReqHandler.setParameter("body", WeChatConfig.BODY);
        prepayReqHandler.setParameter("mch_id", WeChatConfig.MCH_ID);
        String time = Long.toString(System.currentTimeMillis() / 1000);
        String idStr = Long.toString(System.currentTimeMillis());
        prepayReqHandler.setParameter("nonce_str", idStr);
        prepayReqHandler.setParameter("notify_url", WeChatConfig.NOTIFY_URL);
        prepayReqHandler.setParameter("out_trade_no", orderId);
        prepayReqHandler.setParameter("spbill_create_ip", "47.103.22.134");
        prepayReqHandler.setParameter("total_fee", Integer.toString(value));
        prepayReqHandler.setParameter("trade_type", "MWEB");
        prepayReqHandler.setParameter("time_start", time);
        prepayReqHandler.setParameter("attach", backJsonInfo);

        /**
         * 注意签名（sign）的生成方式，具体见官方文档（传参都要参与生成签名，且参数名按照字典序排序，最后接上APP_KEY,转化成大写）
         */
        prepayReqHandler.setParameter("sign", prepayReqHandler.createMD5Sign());
        prepayReqHandler.setGateUrl(WeChatConfig.GATEURL);
        String prepayid;
        WxNotifyParam param = new WxNotifyParam();

        try {
            prepayid = prepayReqHandler.sendPrepay();
            // 若获取prepayid成功，将相关信息返回客户端
            if (prepayid != null && !prepayid.equals("")) {
                /**
                 * 签名方式与上面类似
                 */
                param.setPrepayid(prepayid);

                String signs = "appid=" +" wxbc645cafc9875782" +
                        "&noncestr=" + idStr +
                        "&package=Sign=WXPay&partnerid=" + WeChatConfig.PARTNER_ID +
                        "&prepayid=" + prepayid +
                        "&timestamp=" + time +
                        "&key=" + WeChatConfig.APP_KEY;
                param.setSign(Md5Util.MD5Encode(signs, "utf8").toUpperCase());
                param.setAppid("wxbc645cafc9875782");
                // 与请求prepayId时值一致
                param.setTimestamp(time);
                param.setNoncestr(idStr);
                // 固定常量
                param.setPackages("Sign=WXPay");
                param.setPartnerid(WeChatConfig.PARTNER_ID);
                return param;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

}
